package avicit.bdp.dds.api.controller;

import avicit.bdp.common.dto.query.dds.ProcessDefinitionQuery;
import avicit.bdp.dds.api.dto.ProcessDefinitionStateDto;
import avicit.bdp.dds.api.service.ProcessDefinitionService;
import avicit.bdp.dds.common.Constants;
import avicit.bdp.dds.common.utils.ParameterUtils;
import avicit.bdp.dds.dao.entity.ProcessDefinition;
import avicit.bdp.dds.dao.entity.ProcessDefinitionHistory;
import avicit.bdp.dds.dispatch.model.TaskNode;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/** 流程定义处理器 */
@RestController
@Api(tags = "流程定义REST接口")
@RequestMapping("/api/bdp/dds/process")
public class ProcessDefinitionRest {
  private static final Logger logger = LoggerFactory.getLogger(ProcessDefinitionRest.class);

  @Autowired private ProcessDefinitionService processDefinitionService;

  /** 分页查询流程定义 */
  @ApiOperation(value = "分页查询流程定义")
  @ApiImplicitParams({
    @ApiImplicitParam(name = "projectName", value = "空间名称", type = "String"),
    @ApiImplicitParam(name = "searchVal", value = "关键字", type = "String"),
    @ApiImplicitParam(name = "userId", value = "用户名id", dataType = "Int"),
    @ApiImplicitParam(name = "pageNo", value = "当前页", dataType = "Int"),
    @ApiImplicitParam(name = "pageSize", value = "每页大小", dataType = "Int")
  })
  @GetMapping(value = "/list-paging")
  public ResponseMsg<QueryRespBean<ProcessDefinition>> queryProcessDefinitionListPaging(
      @RequestParam(value = "projectName", required = false) String projectName,
      @RequestParam(value = "searchVal", required = false) String searchVal,
      @RequestParam(value = "userId", required = false) String userId,
      @RequestParam("pageNo") Integer pageNo,
      @RequestParam("pageSize") Integer pageSize) {
    ResponseMsg<QueryRespBean<ProcessDefinition>> responseMsg = new ResponseMsg<>();
    searchVal = ParameterUtils.handleEscapes(searchVal);
    QueryRespBean<ProcessDefinition> queryRespBean =
        processDefinitionService.queryProcessDefinitionListPaging(
            null, projectName, searchVal, pageNo, pageSize, userId);
    responseMsg.setResponseBody(queryRespBean);
    return responseMsg;
  }

  /**
   * 创建工作流
   *
   * @param processDefinition 流程定义
   * @return 创建结果
   */
  @PostMapping(value = "/create")
  @ApiOperation(value = "创建工作流")
  public ResponseMsg<String> createProcessDefinition(
      @RequestBody ProcessDefinition processDefinition) {
    if (processDefinition == null || processDefinition.getType() == null) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("create process definition: {}", processDefinition);

    ResponseMsg<String> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.createProcessDefinition(processDefinition));
    return responseMsg;
  }

  @GetMapping(value = "/getProcessDefinition")
  @ApiImplicitParam(name = "id", value = "id", type = "String")
  @ApiOperation(value = "获取流程定义")
  public ResponseMsg<ProcessDefinition> getProcessDefinition(
      @RequestParam(value = "id") String id) {
    if (id == null) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("get process definition id: {}", id);

    ResponseMsg<ProcessDefinition> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(processDefinitionService.getProcessDefinition(id));
    return responseMsg;
  }

  /**
   * 修改工作流
   *
   * @param processDefinition 流程定义
   * @return 修改结果
   */
  @PostMapping(value = "/update")
  @ApiOperation(value = "修改工作流")
  public ResponseMsg<Boolean> updateProcessDefinition(
      @RequestBody ProcessDefinition processDefinition) {
    if (processDefinition == null || StringUtils.isBlank(processDefinition.getId())) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("update process definition: {}", processDefinition);

    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.updateProcessDefinition(processDefinition));
    return responseMsg;
  }

  /**
   * 启用/停用工作流
   *
   * @param processDefinitionId 流程定义ID
   * @param releaseState 启用状态
   * @return 执行结果
   */
  @ApiOperation(value = "启用/停用工作流")
  @ApiImplicitParams({
    @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", type = "String"),
    @ApiImplicitParam(name = "releaseState", value = "启用状态", type = "Int")
  })
  @GetMapping(value = "/release")
  public ResponseMsg<Boolean> releaseProcessDefinition(
      @RequestParam(value = "processDefinitionId") String processDefinitionId,
      @RequestParam(value = "releaseState") int releaseState) {

    logger.info(
        "release process definition, project id={}, release state={}",
        processDefinitionId,
        releaseState);

    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.releaseProcessDefinition(processDefinitionId, releaseState));
    return responseMsg;
  }

  /**
   * 删除工作流
   *
   * @param processDefinitionId 流程定义ID
   * @return 删除结果
   */
  @ApiOperation(value = "删除工作流")
  @ApiImplicitParam(name = "processDefinitionId", value = "流程定义ID", type = "String")
  @GetMapping(value = "/delete")
  public ResponseMsg<Boolean> deleteProcessDefinitionById(
      @RequestParam("processDefinitionId") String processDefinitionId) {
    if (StringUtils.isBlank(processDefinitionId)) {
      logger.error("流程定义ID为null");
      throw new BusinessException("流程定义ID为null");
    }

    logger.info("delete process definition by id, id={}", processDefinitionId);

    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.deleteProcessDefinitionById(processDefinitionId));
    return responseMsg;
  }

  /**
   * 批量删除工作流
   *
   * @param processDefinitionIds 流程定义ID集合
   * @return 删除失败的ID 集合
   */
  @ApiOperation(value = "批量删除工作流")
  @ApiImplicitParam(name = "processDefinitionIds", value = "流程定义ID集合，逗号分隔", type = "String")
  @GetMapping(value = "/batch-delete")
  public List<String> batchDeleteProcessDefinitionByIds(
      @RequestParam("processDefinitionIds") String processDefinitionIds) {
    logger.info(
        "delete process definition by ids, process definition ids={}", processDefinitionIds);

    List<String> deleteFailedIdList = new ArrayList<>();
    if (StringUtils.isNotEmpty(processDefinitionIds)) {
      String[] processDefinitionIdArray = processDefinitionIds.split(Constants.COMMA);
      for (String processDefinitionId : processDefinitionIdArray) {
        try {
          boolean isDelete =
              processDefinitionService.deleteProcessDefinitionById(processDefinitionId);
          if (!isDelete) {
            deleteFailedIdList.add(processDefinitionId);
            logger.error("delete processDefinition {} failed.", processDefinitionId);
          }
        } catch (Exception e) {
          deleteFailedIdList.add(processDefinitionId);
        }
      }
    }

    if (CollectionUtils.isNotEmpty(deleteFailedIdList)) {
      logger.error(
          MessageFormat.format(
              "batch delete process definition by ids {0} error",
              String.join(",", deleteFailedIdList)));
      throw new BusinessException(
          String.format(
              "batch delete process definition by ids %s error",
              String.join(",", deleteFailedIdList)));
    }

    return deleteFailedIdList;
  }

  /**
   * 删除工作流；---提供给数据开发平台使用，临时新增，后续接口归一
   *
   * @param processDefinitionQuery 流程查询参数
   * @return 删除结果
   */
  @GetMapping(value = "/delete2")
  @ApiOperation(value = "删除工作流")
  public ResponseMsg<Boolean> deleteProcessDefinitionById2(
      @RequestBody ProcessDefinitionQuery processDefinitionQuery) {
    if (processDefinitionQuery == null
        || StringUtils.isBlank(processDefinitionQuery.getProcessDefinitionId())) {
      logger.error("流程定义ID为null");
      throw new BusinessException("流程定义ID为null");
    }

    logger.info(
        "delete process definition by id, id={}", processDefinitionQuery.getProcessDefinitionId());

    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.deleteProcessDefinitionById(
            processDefinitionQuery.getProcessDefinitionId()));

    return responseMsg;
  }

  /**
   * 批量删除工作流;---提供给数据开发平台使用，临时新增，后续接口归一
   *
   * @param processDefinitionQuery 流程查询参数
   * @return 删除失败的ID 集合
   */
  @GetMapping(value = "/batch-delete2")
  @ApiOperation(value = "批量删除工作流")
  public List<String> batchDeleteProcessDefinitionByIds2(
      @RequestBody ProcessDefinitionQuery processDefinitionQuery) {
    if (processDefinitionQuery == null
        || StringUtils.isBlank(processDefinitionQuery.getProcessDefinitionIds())) {
      logger.error("流程定义ID为null");
      throw new BusinessException("流程定义ID为null");
    }

    String processDefinitionIds = processDefinitionQuery.getProcessDefinitionIds();

    logger.info(
        "delete process definition by ids, process definition ids = {}", processDefinitionIds);

    List<String> deleteFailedIdList = new ArrayList<>();
    if (StringUtils.isNotEmpty(processDefinitionIds)) {
      String[] processDefinitionIdArray = processDefinitionIds.split(Constants.COMMA);
      for (String processDefinitionId : processDefinitionIdArray) {
        try {
          boolean isDelete =
              processDefinitionService.deleteProcessDefinitionById(processDefinitionId);
          if (!isDelete) {
            deleteFailedIdList.add(processDefinitionId);
            logger.error("delete processDefinition {} failed.", processDefinitionId);
          }
        } catch (Exception e) {
          deleteFailedIdList.add(processDefinitionId);
        }
      }
    }

    if (CollectionUtils.isNotEmpty(deleteFailedIdList)) {
      logger.error(
          String.format(
              "batch delete process definition by ids %s error",
              String.join(",", deleteFailedIdList)));
    }

    return deleteFailedIdList;
  }

  /**
   * 首页大屏统计流程任务接口
   *
   * @param filed 统计字段 【type, projectId】
   * @return 任务统计结果
   */
  @ApiOperation(value = "大屏统计")
  @ApiImplicitParam(name = "filed", value = "统计字段", type = "String")
  @GetMapping(value = "/bigScreen")
  public ResponseMsg<List<ProcessDefinitionStateDto>> bigScreen(
      @RequestParam(value = "filed") String filed) {
    if (StringUtils.isBlank(filed)) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }
    ResponseMsg<List<ProcessDefinitionStateDto>> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(processDefinitionService.bigScreen(filed));
    return responseMsg;
  }

  /** 获取所有流程定义 */
  @ApiOperation(value = "获取所有流程定义")
  @ApiImplicitParams({
    @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", type = "String"),
    @ApiImplicitParam(name = "projectId", value = "数据空间id", type = "String")
  })
  @GetMapping(value = "/getAllProcessDefinitionList")
  public ResponseMsg<List<ProcessDefinition>> getAllProcessDefinitionList(
      @RequestParam(value = "projectId") String projectId,
      @RequestParam(value = "processDefinitionId", required = false) String processDefinitionId) {
    if (projectId == null) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("get project id: {}", projectId);

    ResponseMsg<List<ProcessDefinition>> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.getAllProcessDefinitionList(projectId, processDefinitionId));
    return responseMsg;
  }

  /** 获取所有节点列表 */
  @ApiOperation(value = "获取所有节点列表")
  @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", type = "String")
  @GetMapping(value = "/getAllTaskNodeList")
  public ResponseMsg<List<TaskNode>> getAllTaskNodeList(
      @RequestParam(value = "processDefinitionId") String processDefinitionId) {
    if (processDefinitionId == null) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("get processDefinitionId: {}", processDefinitionId);

    ResponseMsg<List<TaskNode>> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(processDefinitionService.getAllTaskNodeist(processDefinitionId));
    return responseMsg;
  }

  /** 获取所有节点列表 */
  @ApiOperation(value = "获取所有节点列表")
  @ApiImplicitParam(name = "processDefinitionIdList", value = "流程定义id集合，逗号分隔", type = "String")
  @GetMapping(value = "/getTaskNodeListByDefinitionIdList")
  public ResponseMsg<Map<String, List<TaskNode>>> getTaskNodeListByDefinitionIdList(
      @RequestParam("processDefinitionIdList") String processDefinitionIdList) {
    if (processDefinitionIdList == null) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("get processDefinitionIdList: {}", processDefinitionIdList);

    ResponseMsg<Map<String, List<TaskNode>>> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.getTaskNodeListByDefinitionIdList(processDefinitionIdList));
    return responseMsg;
  }

  /** 获取历史版本 */
  @ApiOperation(value = "获取历史版本")
  @ApiImplicitParams({
    @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", type = "String"),
    @ApiImplicitParam(name = "pageNo", value = "当前页", type = "Int"),
    @ApiImplicitParam(name = "pageSize", value = "每页大小", type = "Int")
  })
  @GetMapping(value = "/getDefinitionHistoryList")
  public ResponseMsg<QueryRespBean<ProcessDefinitionHistory>> getDefinitionHistoryList(
      @RequestParam("processDefinitionId") String processDefinitionId,
      @RequestParam(defaultValue = "1", required = false) Integer pageNo,
      @RequestParam(defaultValue = "10", required = false) Integer pageSize) {
    ResponseMsg<QueryRespBean<ProcessDefinitionHistory>> responseMsg = new ResponseMsg<>();

    QueryRespBean<ProcessDefinitionHistory> queryRespBean =
        processDefinitionService.getDefinitionHistoryList(processDefinitionId, pageNo, pageSize);
    responseMsg.setResponseBody(queryRespBean);
    return responseMsg;
  }

  /** 清空历史版本 */
  @ApiOperation(value = "清空历史版本")
  @ApiImplicitParam(
      name = "processDefinitionId",
      value = "流程定义id",
      dataType = "String",
      paramType = "body",
      required = true)
  @PostMapping(value = "/deleteProcessDefinitionHistory")
  public ResponseMsg<Boolean> deleteProcessDefinitionHistory(
      @ApiIgnore @RequestBody Map<String, String> queryMap) {
    String processDefinitionId = queryMap.get("processDefinitionId");
    if (StringUtils.isBlank(processDefinitionId)) {
      throw new BusinessException("流程定义ID为null");
    }

    ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.deleteProcessDefinitionHistory(processDefinitionId));
    return responseMsg;
  }

  /** 导出流程定义 */
  @ApiOperation(value = "导出流程定义")
  @ApiImplicitParam(name = "id", value = "id", type = "String")
  @GetMapping(value = "/export")
  public void exportFlow(@RequestParam(value = "id") String id, HttpServletResponse response) {
    processDefinitionService.exportFlow(id, response);
  }

  /**
   * 导入流程定义
   *
   * @param file
   * @return
   */
  @ApiOperation(value = "导入流程定义")
  @ApiImplicitParam(name = "file", value = "文件", type = "MultipartFile")
  @PostMapping(value = "/import")
  public ResponseMsg<ProcessDefinition> importFlow(MultipartFile file) {
    ResponseMsg<ProcessDefinition> responseMsg = new ResponseMsg<>();

    responseMsg.setResponseBody(processDefinitionService.importFlow(file));

    return responseMsg;
  }

  /** 根据标准sql获取字段名 */
  @ApiOperation(value = "解析sql字段")
  @ApiImplicitParam(name = "sql", value = "sql脚本", type = "String")
  @GetMapping(value = "/getCloumnNamesBysQL")
  public ResponseMsg<List<String>> getCloumnNamesBysQL(@RequestParam("sql") String sql) {
    ResponseMsg<List<String>> responseMsg = new ResponseMsg<>();
    List<String> columnList = processDefinitionService.getCloumnNamesBysQL(sql);
    responseMsg.setResponseBody(columnList);
    return responseMsg;
  }

  /**
   * 创建并运行工作流
   *
   * @param processDefinition 流程定义
   * @return 运行实例Id
   */
  @PostMapping(value = "/createAndRun")
  @ApiOperation(value = "创建工作流")
  public ResponseMsg<String> createAndRunProcessDefinition(
      @RequestBody ProcessDefinition processDefinition) throws ParseException {
    if (processDefinition == null || processDefinition.getType() == null) {
      logger.error("参数为空");
      throw new BusinessException("参数为空");
    }

    logger.info("create process definition: {}", processDefinition);
    String processDefinitionId =
        processDefinitionService.createAndRunProcessDefinition(processDefinition);
    ResponseMsg<String> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(processDefinitionId);
    return responseMsg;
  }

  @GetMapping(value = "/queryLastOneProcessId")
  @ApiOperation(value = "创建工作流")
  public ResponseMsg<String> queryLastOneProcessId(
      @RequestParam(value = "processDefinitionId") String processDefinitionId) {

    ResponseMsg<String> responseMsg = new ResponseMsg<>();
    responseMsg.setResponseBody(
        processDefinitionService.queryLastOneProcessId(processDefinitionId));
    return responseMsg;
  }
}
